package main

/*
目前应用redis最广泛的应该是新浪微博平台，其次还有Facebook收购的图片社交网站instagram。以及其他一些有名的互联网企业
Go目前支持redis的驱动有如下
https://github.com/garyburd/redigo (推荐)
https://github.com/go-redis/redis
https://github.com/hoisie/redis
https://github.com/alphazero/Go-Redis
https://github.com/simonz05/godis
*/
import (
	"fmt"
	"github.com/garyburd/redigo/redis"
	"os"
	"os/signal"
	"syscall"
	"time"
)

var (
	Pool *redis.Pool
)

func init() {
	redisHost := "test-db.xianshuabao.com:6379"
	Pool = newPool(redisHost, "123456")
	close()
}

func newPool(server string, password string) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     3,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			var c redis.Conn
			var err error
			if len(password) > 0 {
				c, err = redis.Dial("tcp", server, redis.DialPassword(password))
			} else {
				c, err = redis.Dial("tcp", server)
			}
			if err != nil {
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}

func close() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	signal.Notify(c, syscall.SIGKILL)
	go func() {
		<-c
		Pool.Close()
		os.Exit(0)
	}()
}

func Get(key string) ([]byte, error) {
	conn := Pool.Get()
	defer conn.Close()
	var data []byte
	data, err := redis.Bytes(conn.Do("GET", key))
	if err != nil {
		return data, fmt.Errorf("error get key %s: %v", key, err)
	}
	return data, err
}

func GetString(key string) (string, error) {
	conn := Pool.Get()
	defer conn.Close()
	var data string
	data, err := redis.String(conn.Do("GET", key))
	if err != nil {
		return data, fmt.Errorf("error get key %s: %v", key, err)
	}
	return data, err
}

func Set(key string, data []byte, expireSeconds int) bool {
	conn := Pool.Get()
	defer conn.Close()
	_, err := conn.Do("SET", key, data)
	if err != nil {
		println("error set key ", key, " : ", err)
		return false
	}
	if expireSeconds > 0 {
		_, err = conn.Do("EXPIRE", key, expireSeconds)
		if err != nil {
			println("error expire the key ", key, " for ", expireSeconds, " seconds")
		}
	}
	return true
}

func SetString(key string, data string, expireSeconds int) bool {
	conn := Pool.Get()
	defer conn.Close()
	_, err := conn.Do("SET", key, data)
	if err != nil {
		fmt.Println("error set key ", key, " : ", err)
		return false
	}
	if expireSeconds > 0 {
		_, err = conn.Do("EXPIRE", key, expireSeconds)
		if err != nil {
			println("error expire the key ", key, " for ", expireSeconds, " seconds")
		}
	}
	return true
}

func main() {
	res := SetString("test-go", "hello go 2020", 100)
	println("SetString", res)
	res = Set("test-go-byte", []byte("hello go 2020.12.14"), 200)
	println("Set", res)
	test, err := Get("test-go")
	fmt.Println(test, err)
	test2, err := GetString("test-go-byte")
	fmt.Println(test2, err)
	test3, err := GetString("test-go")
	fmt.Println(test3, err)
}
